# node net/tcp.py

import asyncore
import socket
import string
import logging

from tools import parser
from tools import config

BUF = 1024

logging.basicConfig(level = logging.DEBUG, format="%(created)-15s %(msecs)d %(levelname)8s %(thread)d %(name)s %(message)s")
log = logging.getLogger(__name__)

class Client (asyncore.dispatcher) :
	"""Client class: handles the client socket."""

	def __init__ (self, cli_sock, cli_addr, plugin_and_rb):
		"""Initial stuff for the Client"""
		self.debug = config.getDebug ()
		if self.debug :
			log.debug("__init__")
		self.ready_to_send = False
		asyncore.dispatcher.__init__ (self, cli_sock)
		self.ready_to_send = False
		self.data_out = ""
		self.pl_and_rb = plugin_and_rb
		self.send (".") # the server's handle_connect won't run without this

	def handle_write (self) :
		"""If we have something to send, we send it out."""
		if self.debug :
			log.debug ("handle_write")
		if self.data_out :
			sent = self.send (self.data_out)
			if self.debug :
				log.debug ("data sent")
			self.data_out = self.data_out[sent:]
		else:
			if self.debug :
				log.debug ("nothing to send")
		if len (self.data_out) == 0:
			self.ready_to_send = False

	def handle_read (self) :
		"""Tells what to do, if we can read from socket."""
		if self.debug :
			log.debug ("tcp.handle_read")
		data_in = self.recv (BUF)
		if self.debug :
			log.debug ("after recv")
		if data_in :
			if self.debug :
				log.debug ("got data")
			msgs = list(string.split (data_in, "\r\n"))
			for msg in msgs:
				parser.parsemsg (msg,self, self.pl_and_rb)
		else:
			if self.debug :
				log.debug ("no data")

	def handle_close (self) :
		"""Closes socket, if the other side closed."""
		if self.debug :
			log.debug ("handle_close")
		self.close ()

	def readable (self) :
		"""Always return true."""
		return True

	def writable (self) :
		"""Return true, if we have something to send."""
		return self.ready_to_send
	
	def send_msg (self, data) :
		""" """
		self.data_out += data
		self.ready_to_send = True

class Conn (asyncore.dispatcher) :
	"""Extended asyncore.dispatcher class"""
	
	def __init__ (self, plugin_and_rb) :
		"""Initializes the object.
		Parameters: plugin_and_rb : the matrix of plugins and ring buffers."""
		asyncore.dispatcher.__init__ (self)
		self.debug = config.getDebug ()
		if self.debug :
			log.debug ("Conn.__init__")
		self.port = config.getTCPPort ()
		self.pl_and_rb = plugin_and_rb
		self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
		self.bind (("", self.port))
		self.listen (3)

	def handle_accept (self) :
		"""Accepting connections."""
		if self.debug :
			log.debug ("tcp.Conn.handle_accept")
		cli_sock, cli_addr = self.accept ()
		Client (cli_sock, cli_addr, self.pl_and_rb)

	def handle_error (self) :
		"""Handling errors."""
		if self.debug :
			log.debug ("handle_error")
		self.close()
		self.create_socket (socket.AF_INET, socket.SOCK_STREAM)
		self.bind (("", self.port))
		self.listen (3)
